package com.ls.uav_backend.service.impl;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dashscope.app.Application;
import com.alibaba.dashscope.app.ApplicationParam;
import com.alibaba.dashscope.app.ApplicationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.ls.uav_backend.exception.BusinessException;
import com.ls.uav_backend.exception.ErrorCode;
import com.ls.uav_backend.model.dto.EnvironmentDataAIChatDTO;
import com.ls.uav_backend.model.entity.ChatHistory;
import com.ls.uav_backend.model.enums.ChatTypeEnum;
import com.ls.uav_backend.service.AiChatService;
import com.ls.uav_backend.service.ChatHistoryService;
import io.reactivex.Flowable;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import reactor.adapter.rxjava.RxJava2Adapter;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

@Service
public class AiChatServiceImpl implements AiChatService {

    @Resource
    private ChatHistoryService chatHistoryService;

    @Resource
    private ApplicationParam.ApplicationParamBuilder<?, ?> applicationParamBuilder;

    @Resource
    private RedisTemplate<String, List<Message>> redisTemplate;

    @Override
    public Flux<ApplicationResult> chatWithMemory(String userMessage, Integer chatId) throws NoApiKeyException, InputRequiredException {
        if (StrUtil.isBlank(userMessage) || chatId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数不能为空");
        }
        boolean exists = chatHistoryService.queryChain().eq(ChatHistory::getChatId, chatId).exists();
        List<Message> messages = new ArrayList<>();
        ApplicationParam applicationParam = null;
        String cacheKey = String.valueOf(chatId);
        // 如果不存在，则创建新的聊天记录
        if (!exists) {
            applicationParam = applicationParamBuilder.prompt(userMessage).build();
        } else if (redisTemplate.opsForValue().get(cacheKey) != null) {
            // 存在聊天ID，并且缓存中存在之前的聊天记录
            messages = redisTemplate.opsForValue().get(cacheKey);
            applicationParam = applicationParamBuilder
                    .prompt(userMessage)
                    .messages(messages)
                    .build();
        } else if (redisTemplate.opsForValue().get(cacheKey) == null) {
            // 存在聊天ID，但是缓存中不存在之前的聊天记录
            messages = chatHistoryService.loadChatHistory(chatId, 10);
            applicationParam = applicationParamBuilder
                    .prompt(userMessage)
                    .messages(messages)
                    .build();
        }
        // 将用户提问内容记录到记忆中
        assert messages != null;
        messages.add(createMessage(Role.USER, userMessage));
        // 将用户提问内容记录到数据库
        ChatHistory chatHistory = new ChatHistory();
        chatHistory.setChatId(chatId);
        chatHistory.setMessage(userMessage);
        chatHistory.setType(ChatTypeEnum.USER.getValue());
        chatHistoryService.save(chatHistory);
        // 调用SDK发送请求
        Application application = new Application();
        Flowable<ApplicationResult> flowable = application.streamCall(applicationParam);
        Flux<ApplicationResult> contentFlux = RxJava2Adapter.flowableToFlux(flowable);
        // 对响应流进行处理
        StringBuilder contentBuilder = new StringBuilder();
        List<Message> finalMessages = messages;
        return contentFlux.map(chunk -> {
            String text = chunk.getOutput().getText();
            if (StrUtil.isNotBlank(text)) {
                contentBuilder.append(text);
            }
            return chunk;
        }).doOnComplete(() -> {
            // AI回答完毕后，将回答内容更新到数据库
            String aiResponse = contentBuilder.toString();
            ChatHistory aiChatHistory = new ChatHistory();
            aiChatHistory.setChatId(chatId);
            aiChatHistory.setMessage(aiResponse);
            aiChatHistory.setType(ChatTypeEnum.ASSISTANT.getValue());
            chatHistoryService.save(aiChatHistory);
            // 更新AI回答内容缓存
            finalMessages.add(createMessage(Role.ASSISTANT, aiResponse));
            redisTemplate.opsForValue().set(cacheKey, finalMessages, Duration.ofMinutes(15));
        });
    }

    @Override
    public String formatUserPromptWithEnvironmentData(String userMessage, EnvironmentDataAIChatDTO environmentDataAIChatDTO) {
        if (ObjUtil.isNull(environmentDataAIChatDTO)) {
            return userMessage;
        }
        List<String> userPrompt = new ArrayList<>();
        userPrompt.add("请根据以下农作物的环境数据回答用户问题：");

        // 时间戳
        if (environmentDataAIChatDTO.getDataTimestamp() != null) {
            String dataTimestamp = environmentDataAIChatDTO.getDataTimestamp().toString();
            userPrompt.add("数据采集时间：" + dataTimestamp);
        }

        // 室内温度
        if (environmentDataAIChatDTO.getIndoorTemperature() != null) {
            String indoorTemperature = environmentDataAIChatDTO.getIndoorTemperature().toString();
            userPrompt.add("室内温度：" + indoorTemperature + "(℃)");
        }

        // 室外温度
        if (environmentDataAIChatDTO.getOutdoorTemperature() != null) {
            String outdoorTemperature = environmentDataAIChatDTO.getOutdoorTemperature().toString();
            userPrompt.add("室外温度：" + outdoorTemperature + "(℃)");
        }

        // 湿度
        if (environmentDataAIChatDTO.getMoisture() != null) {
            String moisture = environmentDataAIChatDTO.getMoisture().toString();
            userPrompt.add("水份含量：" + moisture + "(%)");
        }

        // 土壤肥料浓度
        if (environmentDataAIChatDTO.getSoilFertilizerConcentration() != null) {
            String soilFertilizerConcentration = environmentDataAIChatDTO.getSoilFertilizerConcentration().toString();
            userPrompt.add("土壤肥料浓度：" + soilFertilizerConcentration + "(%)");
        }

        // 土壤pH值
        if (environmentDataAIChatDTO.getSoilPh() != null) {
            String soilPh = environmentDataAIChatDTO.getSoilPh().toString();
            userPrompt.add("土壤pH值：" + soilPh);
        }

        // 光照强度
        if (environmentDataAIChatDTO.getIllumination() != null) {
            String illumination = environmentDataAIChatDTO.getIllumination().toString();
            userPrompt.add("光照强度：" + illumination + "(Lux)");
        }

        // 电导率
        if (environmentDataAIChatDTO.getConductivity() != null) {
            String conductivity = environmentDataAIChatDTO.getConductivity().toString();
            userPrompt.add("土壤电导率：" + conductivity + "(%)");
        }

        // 钾含量
        if (environmentDataAIChatDTO.getPotassium() != null) {
            String potassium = environmentDataAIChatDTO.getPotassium().toString();
            userPrompt.add("土壤钾含量：" + potassium + "(%)");
        }

        // 氮含量
        if (environmentDataAIChatDTO.getNitrogen() != null) {
            String nitrogen = environmentDataAIChatDTO.getNitrogen().toString();
            userPrompt.add("土壤氮含量：" + nitrogen + "(%)");
        }

        // 磷含量
        if (environmentDataAIChatDTO.getPhosphorus() != null) {
            String phosphorus = environmentDataAIChatDTO.getPhosphorus().toString();
            userPrompt.add("土壤磷含量：" + phosphorus + "(%)");
        }

        // 拼接环境数据提示词后，添加用户原始问题
        userPrompt.add("用户问题：" + userMessage);

        return String.join("\n", userPrompt);
    }


    private Message createMessage(Role role, String content) {
        return Message.builder().role(role.getValue()).content(content).build();
    }
}
